package rd.hardcore.engine.tools.scrollable 
{
	import caurina.transitions.Tweener;
	import flash.display.BitmapData;
	import flash.display.BlendMode;
	import flash.display.DisplayObject;
	import flash.display.GradientType;
	import flash.display.SpreadMethod;
	import flash.display.Sprite;
	import flash.events.Event;
	import flash.events.MouseEvent;
	import flash.geom.Matrix;
	import flash.geom.Rectangle;
	/**
	 * ...
	 * @author Fazermokeur
	 */
	public class ScrollManager extends Sprite
	{
		private var _container	: Sprite;
		private var _content	: DisplayObject;
		private var _rect		: Rectangle;
		private var scroll		: Sprite;
		private var _rightSide	: Boolean;
		private var initScrollPosX : Number;
		//Alpha sur le texte scrollé
		private var scrollMask	: Sprite;
		private var upAlpha		: Number = 1;
		private var downAlpha	: Number = 0;
		private var spMouse		: Sprite;
		private var bgScroll:Sprite;
		
		public function ScrollManager(content:DisplayObject, rect:Rectangle = null, rightSide:Boolean = true) 
		{
			_rect = rect;
			_content = content;
			_rightSide = rightSide;
			_container = new Sprite();
			
			addEventListener(Event.ADDED_TO_STAGE, init);
		}
		
		
		
		override public function get width() : Number
		{
			return _rect ? _rect.width : super.width;
		}
		
		
		override public function get height() : Number
		{
			return _rect ? _rect.height : super.height;
		}
		
		
		
		private function init(e:Event):void 
		{
			removeEventListener(Event.ADDED_TO_STAGE, init);
			//addEventListener(Event.REMOVED_FROM_STAGE, dispose);
			
			spMouse = new Sprite();
			_container.addChild(spMouse);
			_container.addChild(_content);
			addChild(_container);
			
			scrollMask = new Sprite();
			drawMask();
			addChild(scrollMask);
			
			_container.cacheAsBitmap = true;
			scrollMask.cacheAsBitmap = true;
			_container.mask = scrollMask;
			
			if (_rect != null) {
				checkRect();
			}
		}
		
		private function drawMask():void
		{
			scrollMask.graphics.clear();
			var type:String = GradientType.LINEAR;
			var colors:Array = [0xff0000, 0xff0000, 0xff0000, 0xff0000];
			var alphas:Array = [upAlpha, 1, 1,downAlpha];
			var ratios:Array = [0, 15, 240, 255];
			var m:Matrix = new Matrix();
			m.createGradientBox(_rect.width, _rect.height, Math.PI * .5);
			scrollMask.graphics.beginGradientFill(type, colors, alphas, ratios, m);
			//scrollMask.graphics.beginFill(0xff0000);
			scrollMask.graphics.drawRect(_rect.x, _rect.y, _rect.width, _rect.height);
			scrollMask.graphics.endFill();
			
			spMouse.graphics.clear();
			spMouse.graphics.beginFill(0xff0000, 0);
			spMouse.graphics.drawRect(_rect.x, _rect.y, _rect.width, _rect.height);
			spMouse.graphics.endFill();
		}
		
		private function checkRect():void
		{
			if (_container.contains(_content)) {
				
				if (_content.height > _rect.height) {
					activeScrollBar();
					drawMask();
					addChild(scrollMask);
					_container.mask = scrollMask;
					_container.addChildAt(spMouse, 0);
					updateScroll();
				}else {
					ressetAll();
					_container.mask = null;
					if (contains(scrollMask))	removeChild(scrollMask);
					if (_container.contains(spMouse))		_container.removeChild(spMouse);
				}
			}
		}
		
		private function getTexture(c1:uint, c2:uint):BitmapData {
			var bmpd:BitmapData = new BitmapData(4, 4, false, c1);
			bmpd.setPixel32(3, 0, c2);
			bmpd.setPixel32(2, 1, c2);
			bmpd.setPixel32(1, 2, c2);
			bmpd.setPixel32(0, 3, c2);
			return bmpd;
		}
		
		private function activeScrollBar():void
		{
			if (scroll == null) {
				
				bgScroll = new Sprite();
				bgScroll.cacheAsBitmap = true;
				bgScroll.graphics.beginFill(0xa9a9a9);
				bgScroll.graphics.drawRect(0, -1, 15, rect.height+2);
				//bgScroll.addEventListener(MouseEvent.CLICK, handleClick);
				addChild(bgScroll);
				
				
				scroll = new Sprite();
				scroll.blendMode = BlendMode.LAYER;
				scroll.graphics.clear();
				scroll.graphics.beginBitmapFill(getTexture(0x333333, 0x33a9a9a9));
				//scroll.graphics.beginFill(0x333333);
				scroll.graphics.drawRect(1, 0, 13, 32);
				scroll.cacheAsBitmap = true;
				scroll.y = 0;
				addChild(scroll);
				scroll.buttonMode = true;
				//scroll.addEventListener(MouseEvent.MOUSE_DOWN, handleMouseDown);
				
				scroll.alpha = 0;
				bgScroll.alpha = 0;
				
				
				
				//_container.addEventListener(MouseEvent.MOUSE_WHEEL, handleMouseWheel);
			}
			if (_rightSide) initScrollPosX = scroll.x = bgScroll.x = _rect.width + 5;
			else			initScrollPosX = bgScroll.x = scroll.x = -7;
			
		}
		
		private function handleClick(e:MouseEvent):void 
		{
			var targetY:int = (e.currentTarget as Sprite).mouseY - (scroll.height >> 1);
			if (targetY < 0)	targetY = 0;
			if (targetY > (rect.height - scroll.height))	targetY = rect.height - scroll.height;
			addEventListener(Event.ENTER_FRAME, updateScroll);
			Tweener.addTween(scroll, { y:targetY, time:.4, onComplete:handleMouseUp } );
		}
		
		private function handleMouseWheel(e:MouseEvent):void 
		{
			var toY:Number = _content.y + e.delta * 15;
			toY = (toY > _rect.y) ? _rect.y : toY;
			toY = (toY < _rect.height - _content.height) ? _rect.height - _content.height : toY;
			
			Tweener.addTween(_content, { y:toY, time:.5, onUpdate:toContentUpdateScroll } );
		}
		
		private function handleMouseDown(e:MouseEvent):void 
		{
			scroll.removeEventListener(MouseEvent.MOUSE_DOWN, handleMouseDown);
			stage.addEventListener(MouseEvent.MOUSE_UP, handleMouseUp);
			addEventListener(Event.ENTER_FRAME, updateScroll);
			
			scroll.startDrag(false, new Rectangle(initScrollPosX,0,0,_rect.height - scroll.height));
		}
		
		private function handleMouseUp(e:MouseEvent = null):void 
		{
			scroll.addEventListener(MouseEvent.MOUSE_DOWN, handleMouseDown);
			stage.removeEventListener(MouseEvent.MOUSE_UP, handleMouseUp);
			removeEventListener(Event.ENTER_FRAME, updateScroll);
			
			scroll.stopDrag();
		}
		
		private function toContentUpdateScroll():void
		{
			var ratio:Number = (_content.y) / (_rect.height - _content.height);
			setGradients(ratio);
			scroll.y = (_rect.height - scroll.height) * ratio;
		}
		
		private function updateScroll(e:Event = null):void 
		{
			var ratio:Number = (scroll.y) / (_rect.height - scroll.height);
			setGradients(ratio);
			Tweener.addTween(_content, { y:(_rect.height -_content.height ) * ratio, time:.5 } );
		}
		
		private function setGradients(ratio:Number):void
		{
			upAlpha = 1 - ratio * 5;
			downAlpha = 1 - (1 - ratio) * 5;
			drawMask();
		}
		
		private function dispose(e:Event):void 
		{
			removeEventListener(Event.REMOVED_FROM_STAGE, dispose);
			if(_content != null){
				if (_container.contains(_content))	_container.removeChild(_content);
				_content = null;
			}
			if (_container != null)
			{
				_container.removeEventListener(MouseEvent.MOUSE_WHEEL, handleMouseWheel);
				if (contains(_container))	removeChild(_container);
				_container = null;
			}
			ressetAll();
		}
		
		public function get rect():Rectangle { return _rect; }
		
		public function set rect(value:Rectangle):void 
		{
			_rect = value;
			if (_rect != null) {
				_container.scrollRect = _rect;
				checkRect();
				if(spMouse != null){
					spMouse.graphics.beginFill(0xff0000, 0);
					spMouse.graphics.drawRect(_rect.x, _rect.y, _rect.width, _rect.height);
					spMouse.graphics.endFill();
				}
			}else {
				ressetAll();
			}
		}
		
		public function activeScroll():void
		{
			if (_content.height > _rect.height) {
				trace("TRUE");
				if (scroll) {
					trace("SCROLL IS HERE");
					Tweener.addTween([bgScroll, scroll], { alpha:1, time:.5 } );
				
					scroll.addEventListener(MouseEvent.MOUSE_DOWN, handleMouseDown);
					bgScroll.addEventListener(MouseEvent.CLICK, handleClick);
					_container.addEventListener(MouseEvent.MOUSE_WHEEL, handleMouseWheel);
				}
			}
			
			trace("FALSE");
		}
		
		/**
		 * Supprime la scrollBar
		 */
		private function ressetAll():void
		{
			if (scroll != null) {
				if (contains(scroll))	removeChild(scroll);
				scroll.removeEventListener(MouseEvent.MOUSE_DOWN, handleMouseDown);
				scroll = null;

				if( _content && _rect ) _content.y = _rect.y;
			}
		}
		
	}
}